<?xml version="1.0" encoding="utf-8"?>
<Content xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:blueonionsoftware-com:bloget:runtime:data">
  <text>Eric found an obscure but serious bug in my code today. Can you spot it?

&lt;pre style="font-size:larger"&gt;double _result;
double Result
{
    get  { return _result; }

    set 
    { 
         if (_result == value)
             return; 

        _result= value;
        OnResultChanged(); 
    }
}
&lt;/pre&gt;

And the answer...

The bug was in the line:  
 
&lt;code&gt;if (_result == value)&lt;/code&gt;
 
(_result == value) will evaluate to FALSE when both _result and value are NaN (Not a number). Since we use NaN to indicate that a calculation did not produce a result (typically because we're missing an input to the calculation), we notify everyone that the result has changed from NaN to NaN! In the case Eric looked at, the number of event notifications fired by this calc when one of its inputs changed went from 20+ down to 2.
 
This line of code should be changed to:
 
&lt;code&gt;if ((double.IsNaN(_result) &amp;&amp; double.IsNaN(value)) || (_result == value))&lt;/code&gt;
 
or, less obviously but more succinctly:

&lt;code&gt;if (double.Equals(_result, value))&lt;/code&gt;
 
Why does "_result == value" evaluate differently than "double.Equals(_result, value)"? I dunno, but it's by design. the "==" follows from an IEEE floating-point spec which was undoubtly written by a mathematician, not a programmer.
 
Variations of this bug probably exist elsewhere. Be on the lookout for it!
 
And the winner was... Mike Ward who pointed out that we weren't checking for NaN.
 
Honorable mention to... Fred Hall who pointed out that we should guard against recursively firing the event if we get to the Result method while firing the event... And several people who suggested that the test should incoroprate an epsilon value for when the two doubles are "close enough".
 
Best regards,
David Ei
 </text>
  <last_update>2007-10-04T00:52:31.8610806Z</last_update>
  <source_title />
  <source_link />
  <comments />
  <references />
  <attachments />
</Content>